vimfandomcom-20200223-history
Search in current function
Vim can search within a limited scope, for example, finding hits only within the current function, or only within the current brace-delimited block ({...}). This tip provides a script to make searching in a block easy. The procedure works for any program, such as C or C++, where a code block starts with '{' and ends with '}', and where a function starts with '{' at the left margin. Usage After creating the script shown below, edit a program that uses braces ({...}) around blocks. The script defines some mappings using the key which is backslash by default. With the cursor inside a function, type \[ or \{ or \/ to search: ;\[ :Search for visually selected text, or the current word, but only :within the current function ({...} with opening brace in first column). ;\{ :Search for visually selected text, or the current word, but only :within the current block ({...}). ;\/ :Search for visually selected text, or whatever text you enter, but only :within the current function. If you visually select some text then type \[ or \{ or \/, the search locates the next occurrence of the selected text, but only within the specified scope. If there is no selected text: *Typing \[ or \{ searches for the word under the cursor (same as *). *Typing \/ displays a search pattern that defines the scope. Finish the pattern by typing any desired text, then press Enter to complete the search. After searching, press n or N to search for the next or previous occurrence, within the same scope. Script Create file ~/.vim/plugin/scopesearch.vim (Unix) or $HOME/vimfiles/plugin/scopesearch.vim (Windows) containing the script below, then restart Vim. " Search within a scope (a {...} program block). " Version 2010-02-28 from http://vim.wikia.com/wiki/VimTip1530 " Search within top-level block for word at cursor, or selected text. nnoremap [ /=ScopeSearch('', 1) vnoremap [ /=ScopeSearch('[[', 2)gV " Search within current block for word at cursor, or selected text. nnoremap { /=ScopeSearch('[{', 1) vnoremap { /=ScopeSearch('[{', 2)gV " Search within current top-level block for user-entered text. nnoremap / /=ScopeSearch('[[', 0) vnoremap / /=ScopeSearch('[[', 2) " Return a pattern to search within a specified scope, or " return a backslash to cancel search if scope not found. " navigator: a command to jump to the beginning of the desired scope " mode: 0=scope only; 1=scope+current word; 2=scope+visual selection function! s:ScopeSearch(navigator, mode) if a:mode 0 let pattern = '' elseif a:mode 1 let pattern = '\<' . expand('') . '\>' else let old_reg = getreg('@') let old_regtype = getregtype('@') normal! gvy let pattern = escape(@@, '/\.*$^~[') call setreg('@', old_reg, old_regtype) endif let saveview = winsaveview() execute 'normal! ' . a:navigator let first = line('.') normal % let last = line('.') normal % call winrestview(saveview) if first < last return printf('\%%>%dl\%%<%dl%s', first-1, last+1, pattern) endif return "\b" endfunction The script uses [[ to jump to the start of the current function, or [{ to jump to the start of the current block. That should place the cursor on a left brace. Then % is used to jump to the matching right brace. The numbers of the lines holding the left and right braces define the scope. In case no block is detected, the script returns "\b" (a backspace character) which cancels the search that was started by the mapping. See also *[[Searching basic how-to *Search for visually selected text search whole buffer for selected text References * for help on the expression register '=' * * * Comments